#!/bin/bash
# 监控代理数据采集异常自动修复脚本（兼容多种监控服务）
FIX_CODE_ID="monitor"  # 对应知识图谱中"监控工具数据采集异常"故障ID

# 配置参数 - 支持多监控代理自动检测
MONITOR_AGENTS=("node-exporter" "prometheus-node-exporter" "telegraf" "zabbix-agent")  # 常见监控代理列表
SERVICE_MANAGERS=("systemctl" "service")  # 服务管理方式
LOG_FILE="/var/log/monitoring_repair.log"  # 修复操作日志文件
CHECK_INTERVAL=30  # 检查间隔（秒）
RESTART_THRESHOLD=3  # 连续失败重启阈值
METRICS_PORTS=(9100 9273 10050)  # 常见监控代理metrics端口

# 日志函数
log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}

# 检测并获取当前运行的监控代理
detect_running_agent() {
    for agent in "${MONITOR_AGENTS[@]}"; do
        # 尝试用不同的服务管理器检测
        for manager in "${SERVICE_MANAGERS[@]}"; do
            if $manager is-active "$agent" >/dev/null 2>&1; then
                echo "$agent"
                return 0
            fi
        done
        
        # 直接检测进程
        if pgrep -f "$agent" >/dev/null; then
            echo "$agent"
            return 0
        fi
    done
    return 1
}

# 检测metrics端口
detect_metrics_port() {
    local agent=$1
    # 优先根据服务名猜测端口
    case $agent in
        *node-exporter*) echo 9100 ;;
        *telegraf*) echo 9273 ;;
        *zabbix-agent*) echo 10050 ;;
        *) 
            # 扫描常见端口
            for port in "${METRICS_PORTS[@]}"; do
                if nc -z localhost "$port"; then
                    echo "$port"
                    return 0
                fi
            done
            echo 0  # 未检测到端口
        ;;
    esac
}

# 检查监控代理是否运行
check_agent_running() {
    local agent=$1
    for manager in "${SERVICE_MANAGERS[@]}"; do
        if $manager is-active --quiet "$agent"; then
            return 0  # 运行中
        fi
    done
    
    # 直接检查进程
    if pgrep -f "$agent" >/dev/null; then
        return 0
    fi
    
    return 1  # 未运行
}

# 检查数据采集是否正常（通过检查 metrics 端点）
check_data_collection() {
    local port=$1
    if [ "$port" -eq 0 ]; then
        log "未检测到metrics端口，跳过端口检查"
        return 1
    fi
    
    local response_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "http://localhost:${port}/metrics")
    
    if [ "$response_code" -eq 200 ]; then
        return 0  # 采集正常
    else
        return 1  # 采集异常
    fi
}

# 重启监控代理
restart_agent() {
    local agent=$1
    log "尝试重启监控代理: $agent"
    
    # 尝试用不同的服务管理器重启
    for manager in "${SERVICE_MANAGERS[@]}"; do
        if $manager stop "$agent" >/dev/null 2>&1; then
            log "通过$manager成功停止 $agent"
            sleep 2
            if $manager start "$agent" >/dev/null 2>&1; then
                log "通过$manager成功启动 $agent"
                return 0
            fi
        fi
    done
    
    # 服务管理方式失败，尝试直接杀死进程
    log "服务管理方式重启失败，尝试直接重启进程"
    pkill -f "$agent"
    sleep 2
    
    # 查找启动脚本
    local start_scripts=(
        "/usr/bin/$agent"
        "/usr/local/bin/$agent"
        "/etc/init.d/$agent"
    )
    
    for script in "${start_scripts[@]}"; do
        if [ -x "$script" ]; then
            "$script" start >/dev/null 2>&1
            if check_agent_running "$agent"; then
                log "通过启动脚本$script成功启动 $agent"
                return 0
            fi
        fi
    done
    
    log "所有重启方式均失败: $agent"
    return 1
}

# 主逻辑
main() {
    log "开始监控代理健康检查"
    
    # 检测当前运行的监控代理
    local agent=$(detect_running_agent)
    if [ -z "$agent" ]; then
        log "未检测到任何监控代理在运行"
        exit 1
    fi
    log "检测到运行中的监控代理: $agent"
    
    # 检测metrics端口
    local metrics_port=$(detect_metrics_port "$agent")
    log "检测到metrics端口: $metrics_port"
    
    # 检查服务是否运行
    if ! check_agent_running "$agent"; then
        log "$agent 未运行，尝试启动"
        restart_agent "$agent"
        exit $?
    fi
    
    # 检查数据采集是否正常
    if ! check_data_collection "$metrics_port"; then
        log "数据采集异常，尝试重启代理"
        
        # 连续失败计数
        local failure_count=$(grep "数据采集异常" "$LOG_FILE" | tail -n $((CHECK_INTERVAL * 2)) | wc -l)
        
        if [ $failure_count -ge $RESTART_THRESHOLD ]; then
            log "达到连续失败阈值，执行强制重启"
            pkill -9 -f "$agent"
            sleep 2
        fi
        
        restart_agent "$agent"
        
        # 重启后再次检查
        sleep 5
        if check_data_collection "$metrics_port"; then
            log "数据采集已恢复正常"
            exit 0
        else
            log "重启后数据采集仍异常，需要人工干预"
            exit 1
        fi
    else
        log "数据采集正常"
        exit 0
    fi
}

# 执行主逻辑
main
